using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using System.Web.UI.HtmlControls;
using System.Drawing;
using Microsoft.SharePoint.Utilities;
using HTML;

namespace PointBridge.SPDX
{
    public class ContentTypeWrapperGeneratorCtrl : System.Web.UI.UserControl
    {
        protected OptionsSetCtrl wContentTypes;
        protected OptionsSetCtrl wLists;
        protected CheckBox wIsDeriveFromMyClass;
        protected TextBox wDeriveFromClassName;
        protected TextBox wNamespace;
        protected TextBox wOutputDir;
        protected Button wCancel;
        protected Button wGenerate;

        protected void Page_Load(object sender, EventArgs e) { }

        public void Initialize(SPWeb web)
        {
            ResetFields();
            
            _web = web;
            _availableContentTypes.Clear();
            _availableLists.Clear();
            SPDXConfig config = new SPDXConfig(GetItem(web));

            //initialize content type selection
            foreach (SPContentType ct in web.AvailableContentTypes)
            {
                Color color;
                if (ct.ParentWeb.ID == web.ID)
                {
                    if (ct.Hidden == true) color = Color.LightSalmon;
                    else color = Color.Red;
                }
                else
                {
                    if (ct.Hidden == true) color = Color.LightGray;
                    else color = Color.Black;
                }
                _availableContentTypes.Add(new OptionLine(ct.Name, false, 0, color));
            }
            if (IsPostBack != true)
            {
                OptionsSet dbContentTypes = new OptionsSet();
                if (config.contentTypesXml != "") dbContentTypes.ParseXML(new LAHTMLParser(config.contentTypesXml));
                _availableContentTypes.SetValuesFromAnotherSet(dbContentTypes);
            }
            _availableContentTypes.SortAlphabetically();
            wContentTypes.InitOptions(_availableContentTypes, 2);

            //initialize lists selection
            foreach (SPList list in web.Lists)
            {
                Color color;
                if (list.Hidden == true) color = Color.LightSalmon;
                else color = Color.Red;
                _availableLists.Add(new OptionLine(list.Title, false, 0, color));
            }
            if (IsPostBack != true)
            {
                OptionsSet dbLists = new OptionsSet();
                if (config.listsXml != "") dbLists.ParseXML(new LAHTMLParser(config.listsXml));
                _availableLists.SetValuesFromAnotherSet(dbLists);
            }
            _availableLists.SortAlphabetically();
            wLists.InitOptions(_availableLists, 2);

            //initialize simple controls
            if (IsPostBack != true)
            {
                Initialization.InitTextBox(wNamespace, config.myNamespace);
                Initialization.InitCheckBox(wIsDeriveFromMyClass, config.isDeriveFromMyClass);
                Initialization.InitTextBox(wDeriveFromClassName, config.deriveFromClassName);
                Initialization.InitTextBox(wOutputDir, config.outputDir);
            }

            AdjustByValues();
        }
        public static SPListItem GetItem(SPWeb web)
        {
            SPListItem item;
            SPList list;
            try
            {
                list = web.Lists["SPDXConfig_" + web.ID];
            }
            catch (Exception ex)
            {
                throw new PointBridgeEx("Unable to find SPDXConfig list: " + ex.Message);
            }
            if (list.Items.Count == 0) item = list.Items.Add();
            else item = list.Items[0];
            return item;
        }
        public void ResetFields()
        {
            Initialization.ResetControl(wNamespace);
            Initialization.ResetControl(wOutputDir);
            Initialization.ResetControl(wIsDeriveFromMyClass);
            Initialization.ResetControl(wDeriveFromClassName);
        }
        public void AdjustByValues()
        {
            if (wIsDeriveFromMyClass.Checked == true)
            {
                wDeriveFromClassName.Enabled = true;
                wDeriveFromClassName.BackColor = Color.White;
            }
            else
            {
                wDeriveFromClassName.Text = "";
                wDeriveFromClassName.Enabled = false;
                wDeriveFromClassName.BackColor = Color.LightGray;
            }
        }
        protected void ParseFields(SPDXConfig config, bool strict)
        {
            try { wContentTypes.Parse(true, _availableContentTypes); }
            catch (NoOptionsSetEx) { }; //here we ignore a situation when no options are set
            config.contentTypesXml = _availableContentTypes.ToXMLString();

            try { wLists.Parse(true, _availableLists); }
            catch (NoOptionsSetEx) { }; //here we ignore a situation when no options are set
            config.listsXml = _availableLists.ToXMLString();

            config.myNamespace = Parsing.ParseStr(wNamespace, "Namespace", true);
            config.outputDir = Parsing.ParseStr(wOutputDir, "Output Dir", true);
            config.isDeriveFromMyClass = Parsing.ParseBool(wIsDeriveFromMyClass, "Derive From My Class Checkbox", true);
            config.deriveFromClassName = Parsing.ParseStr(wDeriveFromClassName, "My Class Name to derive from", true);        
        }        
        protected bool ProcessFields(SPDXConfig config, bool strict)
        {
            try { ParseFields(config, strict); }
            catch (ParseEx ex)
            {
                Web.Alert(this.Page, "PROBLEM: \\n" + ex.Message);
                return false;
            }
            if (strict == true)
            {
                try
                {
                    config.Validate();
                }
                catch (ValidationEx ex)
                {
                    Web.Alert(this.Page, "PROBLEM: \\n" + ex.Message);
                    Web.MarkError(this.Page, this.ClientID + ":" + ex.varId);
                    return false;
                }
            }
            return true;
        }
        public void Process(SPWeb web)
        {
            try
            {
                SPListItem item = GetItem(web);
                SPDXConfig config = new SPDXConfig(item);

                if (ProcessFields(config, true) == true)
                {
                    CodeGen codeGen = new CodeGen();
                    Dictionary<string, bool> classes = new Dictionary<string, bool>();

                    //generate content type wrappers
                    for (int i = 0; i < _availableContentTypes.count; i++)
                    {
                        if (_availableContentTypes[i].optionValue == true)
                        {
                            string className = CodeGen.ConvertSPNameToCS(_availableContentTypes[i].optionName);
                            if (classes.ContainsKey(className)) throw new PointBridgeEx(string.Format("This setup results in two classes with duplicate name ({0}).", className));
                            classes.Add(className, true);
                            codeGen.GenarateContentTypeWrapper(web.AvailableContentTypes[_availableContentTypes[i].optionName], config, true);
                        }
                    }

                    //generate list wrappers
                    for (int i = 0; i < _availableLists.count; i++)
                    {
                        if (_availableLists[i].optionValue == true)
                        {
                            string className = CodeGen.ConvertSPNameToCS(_availableLists[i].optionName + "ListItem");
                            if (classes.ContainsKey(className)) throw new PointBridgeEx(string.Format("This setup results in two classes with duplicate name ({0}).", className));
                            classes.Add(className, true);
                            codeGen.GenerateListItemWrapper(web.Lists[_availableLists[i].optionName], config, true);
                        }
                    }

                    //generate Container Classes
                    CodeGen.GenerateStaticClasses(config, "ContainerClasses", true);
                }

                config.SaveIntoSPItem(item);
                item.Web.AllowUnsafeUpdates = true;
                item.Update();

                Web.Alert(this.Page, "Code Generated Successfully!");
            }
            catch (Exception ex)
            {
                Web.Alert(this.Page, "Code Generation Failed: " + ex.Message);
            }
        }

        protected void wCancel_Clicked(object sender, System.EventArgs e)
        {
            SPUtility.Redirect(_web.Url, SPRedirectFlags.UseSource, HttpContext.Current);
        }
        protected void wGenerate_Clicked(object sender, System.EventArgs e)
        {
            Process(_web);
        }

        private OptionsSet _availableContentTypes = new OptionsSet();
        private OptionsSet _availableLists = new OptionsSet();
        private SPWeb _web;
    }
}
